﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using GS1.Comunicacion;

namespace PuntoVenta
{
    public partial class frmPrincipal : Form
    {
        private DataTable tbProductos = null;
        
        // lista de productos
        private DataTable tbDetalleProductos = null;

        // Clase cliente socket
        private Cliente cliente = null;

        private const string COMANDO_MOVIMIENTO = "MOV";
        private const string COMANDO_SEPARADOR = "|";
        private const string FORMATO_FECHAHORA = "HH:mm:ss dd/MM/yyyy";

        // Punteros funcion, que apuntan a metodos de manera dinamica
        private delegate void MostrarMensajeDelegate(string mensaje);

        private delegate void MostrarSucesosDelegate(string mensaje);

        public frmPrincipal()
        {
            InitializeComponent();
        }

        private void frmPrincipal_Load(object sender, EventArgs e)
        {
            cargarFormulario();
        }

        private void btnLimpiar_Click(object sender, EventArgs e)
        {
            // Limpia la tabla de productos
            this.tbDetalleProductos.Rows.Clear();
        }

        private void btnCalcular_Click(object sender, EventArgs e)
        {
            calcular();
        }

        private void btnDetener_Click(object sender, EventArgs e)
        {
            desconectarServidorRFID();
        }

        private void btnIniciar_Click(object sender, EventArgs e)
        {
            conectarServidorRFID();
        }

        private void cargarFormulario()
        {
            // Se instancia tabla de productos a pagar
            this.tbDetalleProductos = new DataTable();
            
            // Se define las columnas de la tabla
            this.tbDetalleProductos.Columns.Add("Epc", typeof(string));
            this.tbDetalleProductos.Columns.Add("Descripcion", typeof(string));
            this.tbDetalleProductos.Columns.Add("Cantidad", typeof(int));
            this.tbDetalleProductos.Columns.Add("Precio", typeof(decimal));
            this.tbDetalleProductos.Columns.Add("SubTotal", typeof(decimal), "Cantidad*Precio");

            // Se establece el contenido de la tabla al gridview
            this.dgvDetalle.DataSource = this.tbDetalleProductos;

            // Instancia de tabla de catalogo de productos
            this.tbProductos = new DataTable();
            this.tbProductos.Columns.Add("Epc", typeof(string));
            this.tbProductos.Columns.Add("Descripcion", typeof(string));
            this.tbProductos.Columns.Add("Precio", typeof(decimal));

            // Se agregan productos al catalogo
            this.tbProductos.Rows.Add(new object[] { "302800000000010000000001", "Bolsa de Azucar Rubia", 12.5 });
            this.tbProductos.Rows.Add(new object[] { "302800000000010000000002", "Bolsa de Arroz", 7.5 });
            this.tbProductos.Rows.Add(new object[] { "302800000000010000000003", "Botella aceite", 6.7 });
        }

        private bool validarDetalleProducto(string epc)
        {
            DataRow[] filas = this.tbDetalleProductos.Select("Epc='" + epc + "'", string.Empty);

            if (filas != null && filas.Length > 0)
            {
                return true;
            }

            return false;
        }

        private DataRow obtenerProducto(string epc)
        {
            DataRow[] filas = this.tbProductos.Select("Epc='" + epc + "'", string.Empty);

            if (filas != null && filas.Length > 0)
            {
                return filas[0];
            }

            return null;
        }

        // Metodo que establece la conexion al servidor RFID
        private bool conectarServidorRFID()
        {
            bool resultado = false;

            try
            {
                this.cliente = new Cliente();
                // Se establece la captura del evento recepcion de data
                this.cliente.recepcionData += new Cliente.recepcionDataHandler(cliente_recepcionData);
                // Se establece la captura del evento del cliente
                this.cliente.sucesosCliente += new Cliente.sucesosClienteHandler(cliente_sucesosCliente);
                // Se establece la captura del evento termino de conexion 
                this.cliente.terminoConexion += new Cliente.terminoConexionHanler(cliente_terminoConexion);

                resultado = this.cliente.iniciar("172.16.25.152", 1986);
            }
            catch (Exception se)
            {
                string str;
                str = "Error de conexion el servidor esta operativo?," + se.Message;
                MessageBox.Show(str);
            }

            return resultado;
        }

        // Metodo que detiene la conexion al servidor RFID
        private bool desconectarServidorRFID()
        {
            return this.cliente.detener();
        }

        private void cliente_recepcionData(string mensaje)
        {
            MostrarMensajeDelegate del = new MostrarMensajeDelegate(mostrarMensaje);
            // ejecuta metodo [mostrarMensaje] en el hilo de la aplicacion
            this.BeginInvoke(del, mensaje);
        }

        private void cliente_sucesosCliente(string mensaje)
        {
            MostrarSucesosDelegate del = new MostrarSucesosDelegate(mostrarSucesos);
            // ejecuta metodo [mostrarSucesos] en el hilo de la aplicacion
            this.BeginInvoke(del, mensaje);
        }

        private void cliente_terminoConexion(string mensaje)
        {
            MostrarSucesosDelegate del = new MostrarSucesosDelegate(mostrarDesconexion);
            // ejecuta metodo [mostrarDesconexion] en el hilo de la aplicacion
            this.BeginInvoke(del, mensaje);
        }

        private void mostrarSucesos(string mensaje)
        {
            MessageBox.Show(mensaje);
        }

        private void mostrarDesconexion(string mensaje)
        {
            MessageBox.Show(mensaje);
        }

        private void mostrarMensaje(string mensaje)
        {
            //MOV:300833B2DDD906C000000001|2|+;

            string comando = mensaje.Substring(0, 3); // MOV
            string mensajeProcesado = mensaje.Substring(4); //300833B2DDD906C000000001|2|+
            string[] listaParametros = mensajeProcesado.Split(COMANDO_SEPARADOR.ToCharArray()); //{300833B2DDD906C000000001,2,+}

            string epc = string.Empty;
            string antena = string.Empty;
            string movimiento = string.Empty;

            if (comando.Equals(COMANDO_MOVIMIENTO))
            {
                // Obteniendo codigo epc del activo
                epc = listaParametros[0];//300833B2DDD906C000000001

                // Obteniendo numero de antena
                antena = listaParametros[1];//2

                // Obteniendo direccion del activo
                movimiento = listaParametros[2];
                movimiento = movimiento.Substring(0, movimiento.Length - 1); // +

                //TODO: Implementar logica

                // buscar producto en el catalogo
                DataRow producto = obtenerProducto(epc);

                if (producto != null)
                {
                    if (validarDetalleProducto(epc) == false)
                    {
                        // Agregamos producto al listado de detalle a pagar
                        this.tbDetalleProductos.Rows.Add(new object[] { producto["epc"], 
                                                                        producto["Descripcion"], 
                                                                        1, 
                                                                        producto["Precio"]});

                        calcular();
                    }
                }

            }

        }

        private void calcular()
        {
            decimal totalPagar = 0;
            object total;

            // Suma la columna Subtotal
            total = this.tbDetalleProductos.Compute("SUM(SubTotal)", string.Empty);
            if (total != DBNull.Value)
            {
                // Si es diferente a DBNull, mostrar el total a pagar
                totalPagar = Convert.ToDecimal(total);

                this.txtTotal.Text = total.ToString();
            }
        }
    }
}
